/** @file

  Copyright 2006 - 2013 Unified EFI, Inc.<BR>
  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>

  This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
  which accompanies this distribution.  The full text of the license may be found at 
  http://opensource.org/licenses/bsd-license.php
 
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
**/
/*++

Module Name:

  MemoryAllocationServicesBBTestFunction.c

Abstract:

  Interface Test Cases of Memory Allocation Boot Services

--*/

#include "SctLib.h"
#include "MemoryAllocationServicesBBTestMain.h"

#define ALLOCATEPAGES_MEMORYTYPE_NUM 16

EFI_MEMORY_TYPE AllocatePagesMemoryType[ALLOCATEPAGES_MEMORYTYPE_NUM] = {
  EfiLoaderCode,
  EfiLoaderData,
  EfiRuntimeServicesCode,
  EfiRuntimeServicesData,
  EfiBootServicesCode,
  EfiBootServicesData,
  EfiUnusableMemory,
  EfiACPIReclaimMemory,
  EfiACPIMemoryNVS,
  EfiMemoryMappedIO,
  EfiMemoryMappedIOPortSpace,
  EfiPalCode,
  EfiReservedMemoryType,
  0x80000000,
  0xC0000000,
  0xFFFFFFFF
};

#define ALLOCATEPOOL_MEMORYTYPE_NUM 16

EFI_MEMORY_TYPE AllocatePoolMemoryType[ALLOCATEPOOL_MEMORYTYPE_NUM] = {
  EfiLoaderCode,
  EfiLoaderData,
  EfiRuntimeServicesCode,
  EfiRuntimeServicesData,
  EfiBootServicesCode,
  EfiBootServicesData,
  EfiUnusableMemory,
  EfiACPIReclaimMemory,
  EfiACPIMemoryNVS,
  EfiMemoryMappedIO,
  EfiMemoryMappedIOPortSpace,
  EfiPalCode,
  EfiReservedMemoryType,
  0x80000000,
  0xC0000000,
  0xFFFFFFFF
};

/**
 *  Entrypoint for gtBS->GetMemoryMap() Interface Test.
 *  @param This a pointer of EFI_BB_TEST_PROTOCOL.
 *  @param ClientInterface a pointer to the interface to be tested.
 *  @param TestLevel test "thoroughness" control.
 *  @param SupportHandle a handle containing protocols required.
 *  @return EFI_SUCCESS Finish the test successfully.
 */
//
// TDS 4.1
//
EFI_STATUS
BBTestGetMemoryMapInterfaceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  UINTN                                MemoryMapSize;
  UINTN                                MapKey, MapKey2, MapKey3;
  UINTN                                DescriptorSize;
  UINT32                               DescriptorVersion;
  EFI_TEST_ASSERTION                   AssertionType;
  UINTN                                Index;
  EFI_TPL                              OldTpl;
  EFI_PHYSICAL_ADDRESS                 Memory;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   (VOID **) &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  Status = InitMemoryMap ();
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"InitMemoryMap - Allocate memory map buffer",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status
                   );
    return Status;
  }

  for (Index = 0; Index < TPL_ARRAY_SIZE; Index++) {
    //
    // 4.1.2.1  GetMemoryMap must succeed with valid parameters.
    //
    MemoryMapSize = MemoryMapSizeNeeded;
    OldTpl = gtBS->RaiseTPL (TplArray[Index]);
    Status = gtBS->GetMemoryMap (
                     &MemoryMapSize,
                     (EFI_MEMORY_DESCRIPTOR *)MemoryMap,
                     &MapKey,
                     &DescriptorSize,
                     &DescriptorVersion
                     );
    gtBS->RestoreTPL (OldTpl);
    if (Status == EFI_SUCCESS) {
      AssertionType = EFI_TEST_ASSERTION_PASSED;
    } else {
      AssertionType = EFI_TEST_ASSERTION_FAILED;
    }
    StandardLib->RecordAssertion (
                   StandardLib,
                   AssertionType,
                   Index==0? \
                   gMemoryAllocationServicesInterfaceTestAssertionGuid001: \
                   (Index == 1? \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid001: \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid002),
                   L"BS.GetMemoryMap - Valid parameters",
                   L"%a:%d:Status - %r, TPL - %d",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status,
                   TplArray[Index]
                   );

    //
    // 4.1.2.2  GetMemoryMap should return different MapKey when memory map
    //          is changed.
    //
    MemoryMapSize = MemoryMapSizeNeeded;
    OldTpl = gtBS->RaiseTPL (TplArray[Index]);
    Status = gtBS->GetMemoryMap (
                     &MemoryMapSize,
                     (EFI_MEMORY_DESCRIPTOR *)MemoryMap,
                     &MapKey,
                     &DescriptorSize,
                     &DescriptorVersion
                     );
    gtBS->RestoreTPL (OldTpl);
    if (Status == EFI_SUCCESS) {
      AssertionType = EFI_TEST_ASSERTION_PASSED;
    } else {
      AssertionType = EFI_TEST_ASSERTION_FAILED;
      MapKey = 0;
    }
    StandardLib->RecordAssertion (
                   StandardLib,
                   AssertionType,
                   Index==0? \
                   gMemoryAllocationServicesInterfaceTestAssertionGuid002: \
                   (Index == 1? \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid003: \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid004),
                   L"BS.GetMemoryMap - Get first map key",
                   L"%a:%d:Status - %r, TPL - %d",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status,
                   TplArray[Index]
                   );
    Status = gtBS->AllocatePages (
                     AllocateAnyPages,
                     EfiBootServicesData,
                     1,
                     &Memory
                     );
    if (EFI_ERROR(Status)) {
      StandardLib->RecordAssertion (
                     StandardLib,
                     EFI_TEST_ASSERTION_FAILED,
                     gTestGenericFailureGuid,
                     L"BS.AllocatePages - 1 page EfiBootServicesData",
                     L"%a:%d:Status - %r, TPL - %d",
                     __FILE__,
                     (UINTN)__LINE__,
                     Status,
                     TplArray[Index]
                     );
      continue;
    }
    MemoryMapSize = MemoryMapSizeNeeded;
    OldTpl = gtBS->RaiseTPL (TplArray[Index]);
    Status = gtBS->GetMemoryMap (
                     &MemoryMapSize,
                     (EFI_MEMORY_DESCRIPTOR *)MemoryMap,
                     &MapKey2,
                     &DescriptorSize,
                     &DescriptorVersion
                     );
    gtBS->RestoreTPL (OldTpl);
    if (Status == EFI_SUCCESS) {
      AssertionType = EFI_TEST_ASSERTION_PASSED;
    } else {
      AssertionType = EFI_TEST_ASSERTION_FAILED;
      MapKey2 = 0;
    }
    StandardLib->RecordAssertion (
                   StandardLib,
                   AssertionType,
                   Index==0? \
                   gMemoryAllocationServicesInterfaceTestAssertionGuid003: \
                   (Index == 1? \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid005: \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid006),
                   L"BS.GetMemoryMap - Get second map key",
                   L"%a:%d:Status - %r, TPL - %d",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status,
                   TplArray[Index]
                   );
    Status = gtBS->FreePages (
                     Memory,
                     1
                     );
    if (EFI_ERROR(Status)) {
      StandardLib->RecordAssertion (
                     StandardLib,
                     EFI_TEST_ASSERTION_FAILED,
                     gTestGenericFailureGuid,
                     L"BS.FreePages - 1 page EfiBootServicesData",
                     L"%a:%d:Status - %r, TPL - %d",
                     __FILE__,
                     (UINTN)__LINE__,
                     Status,
                     TplArray[Index]
                     );
      continue;
    }
    MemoryMapSize = MemoryMapSizeNeeded;
    OldTpl = gtBS->RaiseTPL (TplArray[Index]);
    Status = gtBS->GetMemoryMap (
                     &MemoryMapSize,
                     (EFI_MEMORY_DESCRIPTOR *)MemoryMap,
                     &MapKey3,
                     &DescriptorSize,
                     &DescriptorVersion
                     );
    gtBS->RestoreTPL (OldTpl);
    if (Status == EFI_SUCCESS) {
      AssertionType = EFI_TEST_ASSERTION_PASSED;
    } else {
      AssertionType = EFI_TEST_ASSERTION_FAILED;
      MapKey3 = 0;
    }
    StandardLib->RecordAssertion (
                   StandardLib,
                   AssertionType,
                   Index==0? \
                   gMemoryAllocationServicesInterfaceTestAssertionGuid005: \
                   (Index == 1? \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid009: \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid010),
                   L"BS.GetMemoryMap - Get third map key",
                   L"%a:%d:Status - %r, TPL - %d",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status,
                   TplArray[Index]
                   );
    if ((MapKey != 0) && (MapKey2 != 0) && (MapKey3 != 0)
         && (MapKey != MapKey2) && (MapKey2 != MapKey3)) {
      AssertionType = EFI_TEST_ASSERTION_PASSED;
    } else {
      AssertionType = EFI_TEST_ASSERTION_FAILED;
    }
    StandardLib->RecordAssertion (
                   StandardLib,
                   AssertionType,
                   Index==0? \
                   gMemoryAllocationServicesInterfaceTestAssertionGuid006: \
                   (Index == 1? \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid011: \
                    gMemoryAllocationServicesBBTestFunctionAssertionGuid012),
                   L"BS.GetMemoryMap - Different MapKey",
                   L"%a:%d:TPL - %d",
                   __FILE__,
                   (UINTN)__LINE__,
                   TplArray[Index]
                   );

  }

  FreeMemoryMap ();
  return EFI_SUCCESS;
}

/**
 *  Entrypoint for gtBS->AllocatePages() Interface Test.
 *  @param This a pointer of EFI_BB_TEST_PROTOCOL.
 *  @param ClientInterface a pointer to the interface to be tested.
 *  @param TestLevel test "thoroughness" control.
 *  @param SupportHandle a handle containing protocols required.
 *  @return EFI_SUCCESS Finish the test successfully.
 */
//
// TDS 4.2
//
EFI_STATUS
BBTestAllocatePagesInterfaceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  EFI_PHYSICAL_ADDRESS                 Start;
  EFI_PHYSICAL_ADDRESS                 Memory;
  EFI_PHYSICAL_ADDRESS                 Memory2;
  EFI_TEST_ASSERTION                   AssertionType;
  UINTN                                Index;
  UINTN                                TypeIndex;
  EFI_TPL                              OldTpl;
  EFI_MEMORY_DESCRIPTOR                Descriptor;
  UINTN                                PageNum;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   (VOID **) &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  Status = InitMemoryMap ();
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"InitMemoryMap - Allocate memory map buffer",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status
                   );
    return Status;
  }

  for (Index = 0; Index < TPL_ARRAY_SIZE; Index++) {
    //
    // 4.2.2.1  AllocatePages must succeed with valid parameters when Type
    //          is AllocateAnyPages.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPAGES_MEMORYTYPE_NUM; TypeIndex++) {
      OldTpl = gtBS->RaiseTPL (TplArray[Index]);
      Status = gtBS->AllocatePages (
                       AllocateAnyPages,
                       AllocatePagesMemoryType[TypeIndex],
                       1,
                       &Memory
                       );
      gtBS->RestoreTPL (OldTpl);
      if (!EFI_ERROR(Status)) {
        AssertionType = EFI_TEST_ASSERTION_PASSED;
      } else {
        AssertionType = EFI_TEST_ASSERTION_FAILED;
        Memory = 0;
      }
      StandardLib->RecordAssertion (
                     StandardLib,
                     AssertionType,
                     Index==0? \
                     gMemoryAllocationServicesInterfaceTestAssertionGuid007: \
                     (Index == 1? \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid013: \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid014),
                     L"BS.AllocatePages - Type is AllocateAnyPages",
                     L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                     __FILE__,
                     (UINTN)__LINE__,
                     Status,
                     TplArray[Index],
                     AllocatePagesMemoryType[TypeIndex]
                     );
      if (!(Memory & EFI_PAGE_MASK)) {
        AssertionType = EFI_TEST_ASSERTION_PASSED;
      } else {
        AssertionType = EFI_TEST_ASSERTION_FAILED;
      }
      StandardLib->RecordAssertion (
                     StandardLib,
                     AssertionType,
                     Index==0? \
                     gMemoryAllocationServicesInterfaceTestAssertionGuid008: \
                     (Index == 1? \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid015: \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid016),
                     L"BS.AllocatePages - AllocateAnyPages address page-aligned",
                     L"%a:%d:TPL - %d, MemType - %d",
                     __FILE__,
                     (UINTN)__LINE__,
                     TplArray[Index],
                     AllocatePagesMemoryType[TypeIndex]
                     );
      if (Memory != 0) {
        Status = gtBS->FreePages (
                         Memory,
                         1
                         );
        if (EFI_ERROR(Status)) {
          StandardLib->RecordAssertion (
                         StandardLib,
                         EFI_TEST_ASSERTION_FAILED,
                         gTestGenericFailureGuid,
                         L"BS.FreePages - 1 page",
                         L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                         __FILE__,
                         (UINTN)__LINE__,
                         Status,
                         TplArray[Index],
                         AllocatePagesMemoryType[TypeIndex]
                         );
        }
      }
    }

    //
    // 4.2.2.2  AllocatePages must succeed with valid parameters when
    //          Type is AllocateMaxAddress.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPAGES_MEMORYTYPE_NUM; TypeIndex++) {
      Status = GetMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Memory = Descriptor.PhysicalStart +
                 SctLShiftU64 (Descriptor.NumberOfPages, EFI_PAGE_SHIFT);
        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateMaxAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         PageNum/3,
                         &Memory
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid009: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid017: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid018),
                       L"BS.AllocatePages - Type is AllocateMaxAddress",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid010: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid019: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid020),
                       L"BS.AllocatePages - AllocateMaxAddress address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory <= Descriptor.PhysicalStart +
             SctLShiftU64 (Descriptor.NumberOfPages, EFI_PAGE_SHIFT) -
             SctLShiftU64 (PageNum/3, EFI_PAGE_SHIFT)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid011: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid021: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid022),
                       L"BS.AllocatePages - AllocateMaxAddress return Address",
                       L"%a:%d:TPL - %d, MemType - %d, PhysicalStart - 0x%LX, NumberOfPages - 0x%LX, Memory - 0x%LX",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex],
                       Descriptor.PhysicalStart,
                       Descriptor.NumberOfPages,
                       Memory
                       );
        Memory2 = Descriptor.PhysicalStart +
                 SctLShiftU64 (Descriptor.NumberOfPages, EFI_PAGE_SHIFT);
        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateMaxAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         PageNum/3,
                         &Memory2
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory2 = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid012: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid023: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid024),
                       L"BS.AllocatePages - Type is AllocateMaxAddress 2",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory2 & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid013: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid025: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid026),
                       L"BS.AllocatePages - AllocateMaxAddress address 2 page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if ( Memory2 <= Descriptor.PhysicalStart +
             SctLShiftU64 (Descriptor.NumberOfPages, EFI_PAGE_SHIFT) -
             SctLShiftU64 (PageNum/3, EFI_PAGE_SHIFT)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid014: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid027: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid028),
                       L"BS.AllocatePages - AllocateMaxAddress return Address2",
                       L"%a:%d:TPL - %d, MemType - %d, Memory2 - 0x%LX",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex],
                       Memory2
                       );
        if (Memory != 0) {
          Status = gtBS->FreePages (
                           Memory,
                           PageNum/3
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - first PageNum/3",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
        if (Memory2 != 0) {
          Status = gtBS->FreePages (
                           Memory2,
                           PageNum/3
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - second PageNum/3",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
    }

    //
    // 4.2.2.3  AllocatePages must succeed with valid parameters at when
    //          Type is AllocateAddress.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPAGES_MEMORYTYPE_NUM; TypeIndex++) {
      Status = GetSecondMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Start   = Descriptor.PhysicalStart;

        //
        // Some memory types need more alignment than 4K, so
        //
        if (PageNum <= 0x10) {
          break;
        }
        Start   = (Start + 0xFFFF) & 0xFFFFFFFFFFFF0000;
        PageNum = PageNum - EFI_SIZE_TO_PAGES(0x10000);

        Memory  = Start;

        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         PageNum,
                         &Memory
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid015: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid029: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid030),
                       L"BS.AllocatePages - Type is AllocateAddress",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid016: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid031: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid032),
                       L"BS.AllocatePages - AllocateAddress address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory == Start) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid017: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid033: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid034),
                       L"BS.AllocatePages - AllocateAddress return Address",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory != 0) {
          Status = gtBS->FreePages (
                           Memory,
                           PageNum
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - PageNum",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
    }

    //
    // 4.2.2.4  AllocatePages must succeed when request different part memory
    //          in a memory descriptor.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPAGES_MEMORYTYPE_NUM; TypeIndex++) {
      //
      // Allocate font range
      //
      Status = GetMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Start   = Descriptor.PhysicalStart;

        //
        // Some memory types need more alignment than 4K, so
        //
        if (PageNum <= 0x10) {
          break;
        }
        Start   = (Start + 0xFFFF) & 0xFFFFFFFFFFFF0000;
        PageNum = PageNum - EFI_SIZE_TO_PAGES(0x10000);

        Memory  = Start;

        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         PageNum/3,
                         &Memory
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid018: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid035: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid036),
                       L"BS.AllocatePages - front range",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid019: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid037: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid038),
                       L"BS.AllocatePages - front range address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory == Start) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid020: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid039: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid040),
                       L"BS.AllocatePages - front range return Address",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory != 0) {
          Status = gtBS->FreePages (
                           Memory,
                           PageNum/3
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - PageNum/3",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
      //
      // Allocate middle range
      //
      Status = GetMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Start   = Descriptor.PhysicalStart;

        //
        // Some memory types need more alignment than 4K, so
        //
        if (PageNum <= 0x10) {
          break;
        }
        Start   = (Start + 0xFFFF) & 0xFFFFFFFFFFFF0000;
        PageNum = PageNum - EFI_SIZE_TO_PAGES(0x10000);

        Memory = Start + (SctLShiftU64 (PageNum/3, EFI_PAGE_SHIFT) & 0xFFFFFFFFFFFF0000);

        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         PageNum/3,
                         &Memory
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid021: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid041: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid042),
                       L"BS.AllocatePages - middle range",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid022: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid043: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid044),
                       L"BS.AllocatePages - middle range address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory == Start + (SctLShiftU64 (PageNum/3, EFI_PAGE_SHIFT) & 0xFFFFFFFFFFFF0000)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid023: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid045: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid046),
                       L"BS.AllocatePages - middle range return Address",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory != 0) {
          Status = gtBS->FreePages (
                           Memory,
                           PageNum/3
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - PageNum/3",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
      //
      // Allocate back range
      //
      Status = GetMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Start   = Descriptor.PhysicalStart;

        //
        // Some memory types need more alignment than 4K, so
        //
        if (PageNum <= 0x10) {
          break;
        }
        Start   = (Start + 0xFFFF) & 0xFFFFFFFFFFFF0000;
        PageNum = PageNum - EFI_SIZE_TO_PAGES(0x10000);

        Memory  = Start + (SctLShiftU64 (PageNum * 2 / 3, EFI_PAGE_SHIFT) & 0xFFFFFFFFFFFF0000);

        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         PageNum/3,
                         &Memory
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid024: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid047: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid048),
                       L"BS.AllocatePages - back range",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid025: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid049: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid050),
                       L"BS.AllocatePages - back range address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory == Start + (SctLShiftU64 (PageNum * 2 / 3, EFI_PAGE_SHIFT) & 0xFFFFFFFFFFFF0000)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid026: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid051: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid052),
                       L"BS.AllocatePages - back range return Address",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory != 0) {
          Status = gtBS->FreePages (
                           Memory,
                           PageNum/3
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - PageNum/3",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
    }

    //
    // 4.2.2.5  AllocatePages must succeed when request different size memory
    //          in a memory descriptor.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPAGES_MEMORYTYPE_NUM; TypeIndex++) {
      //
      // Allocate 1 page
      //
      Status = GetSecondMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Start   = Descriptor.PhysicalStart;

        //
        // Some memory types need more alignment than 4K, so
        //
        if (PageNum <= 0x10) {
          break;
        }
        Start   = (Start + 0xFFFF) & 0xFFFFFFFFFFFF0000;
        PageNum = PageNum - EFI_SIZE_TO_PAGES(0x10000);

        Memory  = Start;

        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         1,
                         &Memory
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid027: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid053: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid054),
                       L"BS.AllocatePages - 1 page",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid028: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid055: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid056),
                       L"BS.AllocatePages - 1 page address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory == Start) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid029: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid057: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid058),
                       L"BS.AllocatePages - 1 page return Address",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory != 0) {
          Status = gtBS->FreePages (
                           Memory,
                           1
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - 1",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
      //
      // Allocate PageNum-1 pages
      //
      Status = GetSecondMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Start   = Descriptor.PhysicalStart;

        //
        // Some memory types need more alignment than 4K, so
        //
        if (PageNum <= 0x10) {
          break;
        }
        Start   = (Start + 0xFFFF) & 0xFFFFFFFFFFFF0000;
        PageNum = PageNum - EFI_SIZE_TO_PAGES(0x10000);

        Memory  = Start;

        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        if (PageNum != 1) {
          Status = gtBS->AllocatePages (
                           AllocateAddress,
                           AllocatePagesMemoryType[TypeIndex],
                           PageNum - 1,
                           &Memory
                           );
        } else {
          Status = gtBS->AllocatePages (
                           AllocateAddress,
                           AllocatePagesMemoryType[TypeIndex],
                           PageNum,
                           &Memory
                           );
        }
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid030: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid059: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid060),
                       L"BS.AllocatePages - PageNum-1 pages",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid031: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid061: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid062),
                       L"BS.AllocatePages - PageNum-1 pages address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory == Start) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid032: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid063: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid064),
                       L"BS.AllocatePages - PageNum-1 pages return Address",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory != 0) {
          if (PageNum != 1) {
            Status = gtBS->FreePages (
                             Memory,
                             PageNum - 1
                             );
          } else {
            Status = gtBS->FreePages (
                             Memory,
                             PageNum
                             );
          }
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - PageNum-1",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
      //
      // Allocate PageNum pages
      //
      Status = GetSecondMaxFreeMemoryDescriptor (&Descriptor);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.GetMemoryMap - GetMaxFreeMemoryDescriptor",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
      } else {
        PageNum = (UINTN)Descriptor.NumberOfPages;
        Start   = Descriptor.PhysicalStart;

        //
        // Some memory types need more alignment than 4K, so
        //
        if (PageNum <= 0x10) {
          break;
        }
        Start   = (Start + 0xFFFF) & 0xFFFFFFFFFFFF0000;
        PageNum = PageNum - EFI_SIZE_TO_PAGES(0x10000);

        Memory  = Start;

        OldTpl = gtBS->RaiseTPL (TplArray[Index]);
        Status = gtBS->AllocatePages (
                         AllocateAddress,
                         AllocatePagesMemoryType[TypeIndex],
                         PageNum,
                         &Memory
                         );
        gtBS->RestoreTPL (OldTpl);
        if (!EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
          Memory = 0;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid033: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid065: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid066),
                       L"BS.AllocatePages - PageNum pages",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (!(Memory & EFI_PAGE_MASK)) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid034: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid067: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid068),
                       L"BS.AllocatePages - PageNum pages address page-aligned",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory == Start) {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        }
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       Index==0? \
                       gMemoryAllocationServicesInterfaceTestAssertionGuid035: \
                       (Index == 1? \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid069: \
                        gMemoryAllocationServicesBBTestFunctionAssertionGuid070),
                       L"BS.AllocatePages - PageNum pages return Address",
                       L"%a:%d:TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        if (Memory != 0) {
          Status = gtBS->FreePages (
                           Memory,
                           PageNum
                           );
          if (EFI_ERROR(Status)) {
            StandardLib->RecordAssertion (
                           StandardLib,
                           EFI_TEST_ASSERTION_FAILED,
                           gTestGenericFailureGuid,
                           L"BS.FreePages - PageNum",
                           L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                           __FILE__,
                           (UINTN)__LINE__,
                           Status,
                           TplArray[Index],
                           AllocatePagesMemoryType[TypeIndex]
                           );
          }
        }
      }
    }

  }

  FreeMemoryMap ();
  return EFI_SUCCESS;
}

/**
 *  Entrypoint for gtBS->FreePages() Interface Test.
 *  @param This a pointer of EFI_BB_TEST_PROTOCOL.
 *  @param ClientInterface a pointer to the interface to be tested.
 *  @param TestLevel test "thoroughness" control.
 *  @param SupportHandle a handle containing protocols required.
 *  @return EFI_SUCCESS Finish the test successfully.
 */
//
// TDS 4.3
//
EFI_STATUS
BBTestFreePagesInterfaceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  EFI_PHYSICAL_ADDRESS                 Memory;
  EFI_TEST_ASSERTION                   AssertionType;
  UINTN                                Index;
  UINTN                                TypeIndex;
  EFI_TPL                              OldTpl;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   (VOID **) &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  Status = InitMemoryMap ();
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"InitMemoryMap - Allocate memory map buffer",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status
                   );
    return Status;
  }

  for (Index = 0; Index < TPL_ARRAY_SIZE; Index++) {
    //
    // 4.3.2.1  FreePages must succeed with valid parameters.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPAGES_MEMORYTYPE_NUM; TypeIndex++) {
      Status = gtBS->AllocatePages (
                       AllocateAnyPages,
                       AllocatePagesMemoryType[TypeIndex],
                       1,
                       &Memory
                       );

      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.AllocatePages - Type is AllocateAnyPages",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePagesMemoryType[TypeIndex]
                       );
        continue;
      }
      OldTpl = gtBS->RaiseTPL (TplArray[Index]);
      Status = gtBS->FreePages (
                       Memory,
                       1
                       );
      gtBS->RestoreTPL (OldTpl);
      if (!EFI_ERROR(Status)) {
        AssertionType = EFI_TEST_ASSERTION_PASSED;
      } else {
        AssertionType = EFI_TEST_ASSERTION_FAILED;
      }
      StandardLib->RecordAssertion (
                     StandardLib,
                     AssertionType,
                     Index==0? \
                     gMemoryAllocationServicesInterfaceTestAssertionGuid036: \
                     (Index == 1? \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid071: \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid072),
                     L"BS.FreePages - 1 page",
                     L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                     __FILE__,
                     (UINTN)__LINE__,
                     Status,
                     TplArray[Index],
                     AllocatePagesMemoryType[TypeIndex]
                     );
    }

  }

  FreeMemoryMap ();
  return EFI_SUCCESS;
}

/**
 *  Entrypoint for gtBS->AllocatePool () Interface Test.
 *  @param This a pointer of EFI_BB_TEST_PROTOCOL.
 *  @param ClientInterface a pointer to the interface to be tested.
 *  @param TestLevel test "thoroughness" control.
 *  @param SupportHandle a handle containing protocols required.
 *  @return EFI_SUCCESS Finish the test successfully.
 */
//
// TDS 4.4
//
EFI_STATUS
BBTestAllocatePoolInterfaceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  VOID                                 *Memory;
  EFI_TEST_ASSERTION                   AssertionType;
  UINTN                                Index;
  UINTN                                TypeIndex;
  EFI_TPL                              OldTpl;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   (VOID **) &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  Status = InitMemoryMap ();
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"InitMemoryMap - Allocate memory map buffer",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status
                   );
    return Status;
  }

  for (Index = 0; Index < TPL_ARRAY_SIZE; Index++) {
    //
    // 4.4.2.1  AllocatePool must succeed with valid parameters.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPOOL_MEMORYTYPE_NUM; TypeIndex++) {
      OldTpl = gtBS->RaiseTPL (TplArray[Index]);
      Status = gtBS->AllocatePool (
                       AllocatePoolMemoryType[TypeIndex],
                       1,
                       (VOID **)&Memory
                       );
      gtBS->RestoreTPL (OldTpl);
      if (!EFI_ERROR(Status)) {
        AssertionType = EFI_TEST_ASSERTION_PASSED;
      } else {
        AssertionType = EFI_TEST_ASSERTION_FAILED;
        Memory = NULL;
      }
      StandardLib->RecordAssertion (
                     StandardLib,
                     AssertionType,
                     Index==0? \
                     gMemoryAllocationServicesInterfaceTestAssertionGuid037: \
                     (Index == 1? \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid073: \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid074),
                     L"BS.AllocatePool - 1 byte",
                     L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                     __FILE__,
                     (UINTN)__LINE__,
                     Status,
                     TplArray[Index],
                     AllocatePoolMemoryType[TypeIndex]
                     );
      if (Memory != NULL) {
        Status = gtBS->FreePool (
                         Memory
                         );
        if (EFI_ERROR(Status)) {
          StandardLib->RecordAssertion (
                         StandardLib,
                         EFI_TEST_ASSERTION_FAILED,
                         gTestGenericFailureGuid,
                         L"BS.FreePool - 1 byte",
                         L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                         __FILE__,
                         (UINTN)__LINE__,
                         Status,
                         TplArray[Index],
                         AllocatePoolMemoryType[TypeIndex]
                         );
        }
      }
    }

  }

  FreeMemoryMap ();
  return EFI_SUCCESS;
}

/**
 *  Entrypoint for gtBS->FreePool () Interface Test.
 *  @param This a pointer of EFI_BB_TEST_PROTOCOL.
 *  @param ClientInterface a pointer to the interface to be tested.
 *  @param TestLevel test "thoroughness" control.
 *  @param SupportHandle a handle containing protocols required.
 *  @return EFI_SUCCESS Finish the test successfully.
 */
//
// TDS 4.5
//
EFI_STATUS
BBTestFreePoolInterfaceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  VOID                                 *Memory;
  EFI_TEST_ASSERTION                   AssertionType;
  UINTN                                Index;
  UINTN                                TypeIndex;
  EFI_TPL                              OldTpl;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   (VOID **) &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  Status = InitMemoryMap ();
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"InitMemoryMap - Allocate memory map buffer",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status
                   );
    return Status;
  }

  for (Index = 0; Index < TPL_ARRAY_SIZE; Index++) {
    //
    // 4.5.2.1  FreePool must succeed with valid parameters.
    //
    for (TypeIndex = 0; TypeIndex < ALLOCATEPOOL_MEMORYTYPE_NUM; TypeIndex++) {
      Status = gtBS->AllocatePool (
                       AllocatePoolMemoryType[TypeIndex],
                       1,
                       (VOID **)&Memory
                       );
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.AllocatePool - 1 byte",
                       L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                       __FILE__,
                       (UINTN)__LINE__,
                       Status,
                       TplArray[Index],
                       AllocatePoolMemoryType[TypeIndex]
                       );
        continue;
      }
      OldTpl = gtBS->RaiseTPL (TplArray[Index]);
      Status = gtBS->FreePool (
                       Memory
                       );
      gtBS->RestoreTPL (OldTpl);
      if (!EFI_ERROR(Status)) {
        AssertionType = EFI_TEST_ASSERTION_PASSED;
      } else {
        AssertionType = EFI_TEST_ASSERTION_FAILED;
      }
      StandardLib->RecordAssertion (
                     StandardLib,
                     AssertionType,
                     Index==0? \
                     gMemoryAllocationServicesInterfaceTestAssertionGuid038: \
                     (Index == 1? \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid075: \
                      gMemoryAllocationServicesBBTestFunctionAssertionGuid076),
                     L"BS.FreePool - 1 byte",
                     L"%a:%d:Status - %r, TPL - %d, MemType - %d",
                     __FILE__,
                     (UINTN)__LINE__,
                     Status,
                     TplArray[Index],
                     AllocatePoolMemoryType[TypeIndex]
                     );
    }

  }

  FreeMemoryMap ();
  return EFI_SUCCESS;
}
